#!/usr/bin/env python3
from tea5767 import Tea5767, RadioStatus
import math
import time


class Radio:
    SEARCH_UP = 1
    SEARCH_DOWN = 0

    __FILE_PATH = "radio.data"

    def __init__(self):
        self.__driver = Tea5767()

        self.signal_level_threshold = 9

        # 0: play; 1: pause; 2: searching
        self.status = RadioStatus.RADIO_PAUSE
        self.currentFrequency = self.__read_frequency()

        self.play(self.currentFrequency)

    def __save_frequency(self):
        with open(Radio.__FILE_PATH, 'w') as f:
            f.write(self.currentFrequency)

    @classmethod
    def __read_frequency(cls):
        backup = 87.5
        with open(Radio.__FILE_PATH, 'r') as f:
            read_data = f.read()
            if not read_data:
                backup = float(read_data)
        return backup

    def play(self, frequency):
        self.currentFrequency = frequency
        self.status = RadioStatus.RADIO_PLAY
        self.__driver.set_frequency(frequency)
        self.__save_frequency()

    def pause(self):
        self.__driver.set_mute(True)

    def resume(self):
        self.__driver.set_mute(False)

    def __get_next_frequency(self, nowFrequency):
        freq = nowFrequency

        if self.status == RadioStatus.RADIO_SEARCHING_UP:
            freq = nowFrequency + Tea5767.BAND_STEP
            if freq > Tea5767.UPPER_BAND_LIMIT:
                freq = Tea5767.LOWER_BAND_LIMIT
        elif self.status == RadioStatus.RADIO_SEARCHING_DOWN:
            freq = nowFrequency - Tea5767.BAND_STEP
            if freq < Tea5767.LOWER_BAND_LIMIT:
                freq = Tea5767.UPPER_BAND_LIMIT
        return freq

    def seek_station(self, mode=SEARCH_UP):
        """:param mode: Radio.SEARCH_UP or Radio.SEARCH_DOWN"""

        self.status = RadioStatus.RADIO_SEARCHING_UP if mode == Radio.SEARCH_UP else RadioStatus.RADIO_SEARCHING_DOWN

        startFrequency = self.currentFrequency
        nextFreq = startFrequency
        while True:
            nextFreq = self.__get_next_frequency(nextFreq)
            if math.fabs(nextFreq - startFrequency) <= 0.0001:
                nextFreq = startFrequency
                self.play(nextFreq)
                break

            self.__driver.set_frequency(nextFreq, True)
            time.sleep(0.1)

            limit, ready, checkFreq, level = self.__driver.search_query()
            if ready == 1 and level >= self.signal_level_threshold:
                print("ready:", ready, "Frequency tuned: ", checkFreq, "FM (Strong Signal: ", level, ")")
                break
            else:
                print("ready:", ready, "Station skipped: ", checkFreq, "FM (Weak Signal: ", level, ")")

        self.play(nextFreq)


if __name__ == "__main__":
    radio = Radio()
    radio.play(90.5)
    time.sleep(2)
    radio.seek_station(Radio.SEARCH_UP)


